#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         BooleanEditlet.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  This file defines the BooleanEditlet class, that is
#               used to generate boolean value choosers for property editors.
#               (check boxes, radio buttons and dropdown lists.)
#
# See Also:     PropertyEditlet, PropertyRefleciton, 
#               PropertyDefinition, PropertyAccess 
#####################################################################

#####################################################################
## KnowledgeEngine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.Core import *
from Products.KnowledgeEngine.Editlet import Editlet
from Products.KnowledgeEngine.PropertyDefinition import *
from Products.KnowledgeEngine.PropertyTypes import *
from Products.KnowledgeEngine.PropertyFormats import *
from Products.KnowledgeEngine.PropertyStructures import *

#####################################################################
## Zope Library Imports
# (none)
 
#####################################################################
## Python Library Imports
# (none)

#####################################################################
## BooleanEditlet Class Definition
class BooleanEditlet(Editlet):
    """
        An editlet for editing boolean types
    """
    
    #---------------------------------------------------------------#
    
    def isEditable(self, propertyDefinition, propertyAccess=None, value=None, isForConstructor=false, REQUEST=None, context=None):
        """
            Returns if the specified propertyDefinition can be
            edited by this editlet
        """

        return propertyDefinition.getType() == pt_BOOLEAN and propertyDefinition.getStructure() == ps_ATOMIC and not propertyDefinition.hasEnumeratedValues()
        
    #---------------------------------------------------------------#

    def generateEditorForExtJS(self, propertyDefinition, propertyAccess=None, value=None, isForConstructor=false, REQUEST=None, context=None):
        """ Returns Javascript code to render this field using ExtJS """
        
        if isForConstructor or propertyAccess is None:
            value = propertyDefinition.getDefaultValue()
        else:        
            value = propertyAccess.getPropertyValue(propertyDefinition.getIdentity())
        
        propertyFormat = propertyDefinition.getFormat()
        
        #widgetMappings = {
            #pf_CHECKBOX  : 'Checkbox',
            #pf_RADIO     : 'Radio',
            #pf_SELECTION : 'ComboBox',
        #}
            
        #from cStringIO import StringIO
        #out = StringIO()
            
        #widget = widgetMappings[ propertyFormat ]
                
        return """
            keForm.add( new Ext.form.Checkbox({
                fieldLabel: "%s",
                name: "ke%s",     
                checked: %s,                         
            }));
        """ % ( propertyDefinition.getDisplayName(), propertyDefinition.getIdentity(), value and 'true' or 'false')
        
        
            
            
   
    #---------------------------------------------------------------#

    def generateEditorFor(self, propertyDefinition, propertyAccess=None, value=None, isForConstructor=false, REQUEST=None, context=None):
        """
            Returns a HTML editlet for the specified property.
        """

        #determine the display format (checkbox, radio or selection) for the property
        propertyFormat = propertyDefinition.getFormat()
        if propertyFormat == pf_CHECKBOX:
            displayFormat = pf_CHECKBOX
            displayValues = {true:'Yes', false:'No'}
            
        elif propertyFormat[0:len(pf_RADIO)] == pf_RADIO:
            displayFormat = pf_RADIO
            
        elif propertyFormat[0:len(pf_SELECTION)] == pf_SELECTION:
            displayFormat = pf_SELECTION
            
        else:
            displayFormat = pf_CHECKBOX
            displayValues = {true:'Yes', false:'No'}

        #determine the display values (for radio and selection formats)
        if displayFormat == pf_RADIO or displayFormat == pf_SELECTION:
            propertyFormat = propertyFormat[len(displayFormat):]
            
            if propertyFormat == pf_YES_NO:
                displayValues = {true:'Yes', false:'No'}
            elif propertyFormat == pf_ON_OFF:
                displayValues = {true:'On', false:'Off'}
            elif propertyFormat == pf_TRUE_FALSE:
                displayValues = {true:'True', false:'False'}
            elif propertyFormat == pf_SELECTED_UNSELECTED:
                displayValues = {true:'Selected', false:'Not Selected'}
            else:
                displayValues = {true:'Yes', false:'No'}
                                
        #the resulting editlet
        result = ""
        
        #ensure that we use a writeable editlet (if possible) if we are dealing with a mandatory property and we don't yet have a value
        if propertyDefinition.isMandatory() and propertyAccess is not None and (not hasattr(propertyAccess, propertyDefinition.getIdentity()) or getattr(propertyAccess, propertyDefinition.getIdentity()) is None):
            
            #we want an editletEVAP with the most permissions (which may not include write access)
            editletEVAP = propertyDefinition.getConstructorEVAP() | propertyDefinition.getPropertyEditorEVAP()
        
        else:
            #determine the type of editlet we need to produce based on editlet value access permission (EVAM)
            editletEVAP = iif(isForConstructor, propertyDefinition.getConstructorEVAP(), propertyDefinition.getPropertyEditorEVAP())

        #-----------------
        #no property editor is required
        if editletEVAP == evap_NONE:
            result = ""

        #-----------------
        #a read-only property editor is required
        elif editletEVAP == evap_READONLY:

            #get the value for the property
            if isForConstructor or propertyAccess is None:
                value = propertyDefinition.getDefaultValue()
            else:
                value = propertyAccess.getPropertyValue(propertyDefinition.getIdentity())

            #ensure the value is not None
            if value is None:
                value = false
            
            #create the editor
            result = "<table border=1><tr><td>%s</td></tr></table>" % (displayValues[value],)
        
        #-----------------
        #a writeable property editor is required
        else: 
       
            #get the value for the property (if possible)
            if editletEVAP == evap_WRITEONLY:
                value = false
            else:
                if isForConstructor or propertyAccess is None:
                    value = propertyDefinition.getDefaultValue()
                else:
                    #get the value for the property
                    value = propertyAccess.getPropertyValue(propertyDefinition.getIdentity())

            #ensure the value is not None
            if value is None:
                value = false

            #we'll be using this in a few places
            identity = propertyDefinition.getIdentity()
                
            #create the editor
            #-------------------
            if displayFormat == pf_CHECKBOX:
                
                checked = value and " checked " or ""
                    
                result += """
                    <input type='hidden' name='ke%(identity)s:default' value='false'/>
                    <input type='checkbox' id='ke%(identity)s' name='ke%(identity)s' %(checked)s value='true'/>
                """ % locals()
                
            elif displayFormat == pf_RADIO:
            
                result += "<input class='noborder' type='radio' id='ke%s' name='ke%s' value='true'" % (identity,identity)
                if value:
                    result += " checked"
                result += "><b>%s</b>" % (displayValues[true], )
                
                result += "<br>"
                
                result += "<input class='noborder' type='radio' id='ke%s' name='ke%s' value='false'" % (identity,identity)
                if not value:
                    result += " checked"
                result += "><b>%s</b>" % (displayValues[false], )
            
            else:  #pf_SELECTION
                result += "<select id='ke%s' name='ke%s'>" % (identity,identity)
            
                result += "<option value='true'"
                if value:
                    result += " selected"
                result += ">%s</option>" % (displayValues[true], )
                
                result += "<option value='false'"
                if not value:
                    result += " selected"
                result += ">%s</option>" % (displayValues[false], )
                                  
                result += "</select>"        
            
        return result
        
    #---------------------------------------------------------------#

    def containsPropertyValue(self, propertyDefinition, REQUEST):
        """
            Determines if the provided request contains
            a value for the specified propertyDefinition.
            
            This method is used (and is useful for) determining and
            updating the values of properties from property editors.
            
            All editlet implementations must override this method.            
        """
        
        return REQUEST.has_key("ke%s" % (propertyDefinition.getIdentity(),))
        
    #---------------------------------------------------------------#

    def updatePropertyWith(self, propertyDefinition, propertyAccess, REQUEST=None):
        """
            Attempts to update the specified property on the
            object implementing the PropertyAccess interface with the
            specified HTTP REQUEST.
        """

        value = REQUEST["ke%s" % (propertyDefinition.getIdentity(),)] == 'true'

        # Check we have a value if it isMandatory
        propertyDefinition.verifyMandatoryValue(value)

        #set the value for the property
        propertyAccess.setPropertyValue(propertyDefinition.getIdentity(), value)
        
    #---------------------------------------------------------------#

#####################################################################
## Class Initialisation

# Register Editlet Information with the Knowledge Engine
registerEditlet("BooleanEditlet", BooleanEditlet())

#####################################################################
